//! 数据报格式

use crate::consts::*;
use core::sync::atomic::{AtomicU16, Ordering};
use spin::Lazy;

static SN: Lazy<AtomicU16> = Lazy::new(|| {
    AtomicU16::new({
        let mut data: [u8; 2] = [0; 2];
        getrandom::getrandom(&mut data).unwrap();
        ((data[0] as u16) << 8) | (data[1] as u16)
    })
});
/// 设置SN
pub fn set_index(index: u16) {
    SN.store(index, Ordering::Relaxed);
}

/// 数据报头
#[derive(Default)]
pub struct DatagramHeader {
    /// 控制字段
    control: u8,
    /// 序列号
    index: u16,
    /// 本地端口
    srcport: u8,
    /// 目标端口
    dstport: u8,
}
impl DatagramHeader {
    pub fn new(srcport: u8, dstport: u8, index: Option<u16>) -> Self {
        let index = if let Some(i) = index {
            i
        } else {
            SN.fetch_add(1, Ordering::Relaxed)
        };
        DatagramHeader {
            control: 0,
            index,
            srcport: srcport,
            dstport: dstport,
        }
    }
    pub fn control(&self) -> u8 {
        self.control
    }
    pub fn set_control(&mut self, control: u8) {
        self.control = control;
    }
    pub fn index(&self) -> u16 {
        self.index
    }
    pub fn srcport(&self) -> u8 {
        self.srcport
    }
    pub fn dstport(&self) -> u8 {
        self.dstport
    }
    /// 获取数据报的字节流,output长度应等于MAX_LEN
    pub fn generate(&self, body: &[u8]) -> VecDatagram {
        let head = self;
        let mut output = VecDatagram::new();
        output.push(VERSION);
        output.push(head.control);
        output.extend_from_slice(&head.index.to_be_bytes());
        output.push(head.srcport);
        output.push(head.dstport);
        output.extend_from_slice(body);
        return output;
    }
}

/// 数据报
pub struct Datagram<'a> {
    /// 头
    head: DatagramHeader,
    /// 消息体
    body: &'a [u8],
}
impl<'a> Datagram<'a> {
    pub fn head(&self) -> &DatagramHeader {
        &self.head
    }
    pub fn body(&self) -> &[u8] {
        &self.body
    }
    /// 尝试从字节流转为数据报
    pub fn parse(buf: &'a [u8]) -> Result<Datagram<'a>, &'static str> {
        let buf_len = buf.len();
        if buf_len < MIN_LEN {
            return Err("Datagram buf too short.");
        } else if buf_len > MAX_LEN {
            return Err("Datagram buf too long.");
        }

        if buf[0] == VERSION {
            let mut head = DatagramHeader::default();
            head.control = buf[1];
            head.index = (buf[2] as u16) << 8 | buf[3] as u16;
            head.srcport = buf[4];
            head.dstport = buf[5];
            let body = &buf[6..];
            return Ok(Datagram { head, body });
        } else {
            return Err("Datagram no version.");
        }
    }
}
